package upm.pb4agent.team5.common;

import jade.content.Concept;
import jade.core.AID;
import jade.lang.acl.ACLMessage;
import jade.util.leap.ArrayList;
import jade.util.leap.Iterator;
import jade.util.leap.List;

import java.util.Date;

import upm.pb4agent.ontology.EnteringDock;
import upm.pb4agent.ontology.RaceFinished;
import upm.pb4agent.ontology.RaceStarted;
import upm.pb4agent.team5.enumeration.ConfigProperty;
import upm.pb4agent.team5.util.ConfigFile;

class RefereeSendMessage implements Runnable {
	private static final long WAIT_PER_LOOP = 100; // Milliseconds (used in waitStartingRacePeriod)	
	
	private Referee referee = null;
	private Concept concept = null;
	private Date now = null;
	
	public RefereeSendMessage(Referee referee, Concept concept) {
		this.referee = referee;
		this.concept = concept;
	}
	
	private synchronized void sendMessage() throws InterruptedException {
		Iterator iterator = referee.getSubscribers().iterator();

		if (concept instanceof RaceStarted) { // Wait if RaceStarted
			waitStartingRacePeriod();
		} else if (concept instanceof EnteringDock) { // Adding position
			EnteringDock enteringDock = (EnteringDock) concept;
			Object obj = referee.getPositions().get(enteringDock.getDock());
			
			List docks = null;
			if (obj != null)
				docks = (List) obj;
			else {
				docks = new ArrayList();
				referee.getPositions().put(enteringDock.getDock(), docks);
			}
				
			docks.add(enteringDock.getBoatAID());			
			enteringDock.setPosition(docks.size()); // Reseting position
		} else if (concept instanceof RaceFinished) { // Adding position
			RaceFinished raceFinished = (RaceFinished) concept;
			
			referee.incrementNumOfTeamsCrossedFinishLine();
			raceFinished.setPosition(referee.getNumOfTeamsCrossedFinishLine());
		}

		while (iterator.hasNext()) {
			AID subscriber = (AID)iterator.next();
			
			try {
				referee.send(concept, subscriber, ACLMessage.INFORM);
				System.out.println(referee.getLocalName() + ": " + concept.getClass().getSimpleName() + " message sent to " + subscriber.getLocalName());
				
			} catch (Exception e) {
				System.err.println(referee.getLocalName() + ": Cannot send " + concept.getClass().getSimpleName() + " message to " + subscriber.getLocalName());
			} 
		}
	}	
	
	private void waitStartingRacePeriod() throws InterruptedException {
		this.now = new Date();
		long startingRacePeriod = Long.parseLong(
				ConfigFile.getProperty(ConfigProperty.starting_race_period.name())
			);
			
		while ((new Date().getTime() - now.getTime()) > startingRacePeriod) // Stay here when RaceStarted until finish
			Thread.sleep(WAIT_PER_LOOP);
	}

	@Override
	public void run() {
		try {
			sendMessage();
		} catch (InterruptedException e) {
			System.err.println(referee.getLocalName() + ": Error managing message");
		}
	}
	
}
